import random

from simpy import Environment

from x_pc.core import System
from x_pc.core.system_context import SysDataCtx
from x_pc.core.system_jx import SystemJX
from x_pc.core.transport.transport_402_cs import CS
from x_pc.model.model import TaskCtx, check_fix_task, TaskStatus


class SystemCS(System):
    """
    传送系统
    """
    # 仓库系统
    ware_house = None
    # 件箱系统
    system_jx: SystemJX = None
    sys_data: SysDataCtx = None

    # 穿梭 列表
    cs_list: list[CS] = []

    def __init__(self, env: Environment, name: str, system_jx: SystemJX, ware_house, sys_data: SysDataCtx):
        self.cs_list: list[CS] = []
        #
        super().__init__(env, name)
        self.system_jx = system_jx
        self.ware_house = ware_house
        self.sys_data = sys_data
        self.__init_cs_list()

    def __init_cs_list(self):
        cs_list = self.sys_data.get_data(CS)
        for cs in cs_list:
            device = CS(self.env, f'传送-{cs[SysDataCtx.DEVICE_CODE_DB_KEY]}', cs)
            if self.sys_data.is_valid_equ(device):
                self.cs_list.append(device)

    def __get_cs_by_id(self, id: str):
        if id:
            for cs in self.cs_list:
                if cs.id == id:
                    return cs
        return None

    def __process_jxsx(self):
        """
        处理 件箱上下架口 任务
        :return:
        """
        while self.running:
            has_task: bool = False
            # 依次遍历 件箱巷道 查询上下架口是否有任务需要执行
            for lane in self.system_jx.lane_list:
                while lane.jxsx_l and not lane.jxsx_l.is_empty():
                    has_task = True
                    task_ctx = yield lane.jxsx_l.store.get()
                    self.env.process(self.run_task(task_ctx))
                while lane.jxsx_r and not lane.jxsx_r.is_empty():
                    has_task = True
                    task_ctx = yield lane.jxsx_r.store.get()
                    self.env.process(self.run_task(task_ctx))
            if not has_task:
                yield self.env.timeout(1)

    def __process_common(self):
        """
        处理 拆板站台(机械手拆板站台、综合拆板站台) 任务
        :return:
        """
        while self.running:
            while not self.task_list:
                yield self.env.timeout(1)
                continue
            # 实际处理任务
            task_ctx = self.task_list.pop(0)
            self.env.process(self.run_task(task_ctx))

    def run_task(self, task_ctx: TaskCtx):
        """
        处理件箱上下架口 的任务
        :param task_ctx:
        :return:
        """
        task = task_ctx.task
        process = task.process
        step = process.ext_step
        #
        available_css = [_ for _ in self.cs_list if _.id in step.ext_equid_list]
        if not available_css:
            raise Exception(f'[PC] 传送(CS) 设备未找到. task: {task.task_id}, equ_type: {step.ext_equ_type}, equ_id: {step.ext_equid_list}')
        # 随机使用一个设备
        cs: CS = random.choice(available_css)
        #
        process.begin_ts = self.env.now
        pre_process = task.pre_process()
        process.begin_pos = pre_process.end_pos
        process.set_origin_pack_type(pre_process.target_pack_type)
        # 目标数 / 拆分任务数，为后续单个任务的 值
        # process.set_origin_sku_num(int(pre_process.target_sku_num / pre_process.operate_pack_num))
        process.set_origin_sku_num(pre_process.target_sku_num)
        process.operate_pack_type = process.ext_work_type.operate_pack_type
        process.operate_pack_num = 1
        #
        process.device_type = cs.device_type()
        process.device_code = cs.device_code()
        # 耗时
        # msg = f'[PC] CS {cs.name} task: {task.task_id}, time: {ts_str(self.env.now)}'
        # self.sys_data.logger.info(msg)
        yield self.env.timeout(cs.cost() / self.sys_data.time_cost_ratio)
        process.end_ts = self.env.now
        process.end_pos = cs.loc()
        #
        check_fix_task(task)
        # 任务还未完成，继续分发处理
        if TaskStatus.DONE != task.run_status:
            self.ware_house.distribute_task(task_ctx)

    def start(self):
        super().start()
        self.running = True
        # 件箱上下架口 任务
        self.env.process(self.__process_jxsx())
        # 通用任务
        self.env.process(self.__process_common())
